﻿#include "11.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include<time.h>

// 记录所有账号信息
Account accounts[ACCOUNT_SIZE];
int accounts_num = 0;

// 记录所有的书籍信息
Book books[SIZE];
int books_num = 0;

// 记录所有的借阅信息
Borrow borrows[SIZE];
int borrows_num = 0;

// 记录所有的日志信息
OprLog logs[LOG_SIZE];
int logs_num = 0;

// 函数的声明
void LoadAccounts();
void LoadBooks();
void Processlogin();
void ProcessReg();
void SavaSystemData();
void ShowFirstMenu();
void ShowMangerMenu();
void InBook(char* mid);
void ShowOprLog();
void LoadOprLog();
void OutBook(char* mid);
void BorrowBook(char* mid);
void ShowBook();
void SrarchBook(char* mid);
void BackBook(char* mid);//还书
void LoadBorrow();
void ShowStudengtMenu();//学生界面
void BorrowList(char* mid);//个人借阅列表
int main()
{
	// 加载账号信息
	LoadAccounts();

	// 加载书籍信息
	LoadBooks();

	for (;;)
	{
		ShowFirstMenu();
		printf("选择:");
		int choice = 0;
		scanf("%d", &choice);
		getchar();//清除缓存中的回车

		switch (choice)
		{
		case 1:
			Processlogin();
			break;
		case 2:
			ProcessReg();
			break;
		case 3:
			printf("开始退出系统，保存数据中...");
			SavaSystemData();// 开始持久化保存数据
			printf("完成，正常退出!");
			exit(0);
		default:
			printf("非法输入!");
			break;
		}
	}

	return 0;
}


void LoadAccounts()
{
	printf("loading accounts...");
	// 打开文件
	FILE* pf = fopen("account.db", "r");
	if (pf == NULL)
	{
		printf("0\n");
		return;
	}
	// 计算文件大小 / sizeof Account = 账号的个数
	fseek(pf, 0, SEEK_END);
	long fileSize = ftell(pf);
	fseek(pf, 0, SEEK_SET);
	accounts_num = fileSize / sizeof(Account);
	// fread读取文件数据，放到accounts数组里面
	fread(accounts, sizeof(Account), accounts_num, pf);
	// 关闭文件
	fclose(pf);
	printf("%d\n", accounts_num);
}
// 从account.db文件加载账号信息

void LoadBooks()
{
	printf("loading books...");

	FILE* pf = fopen("book.db", "r");
	if (pf == NULL)
	{
		printf("0\n");
		return;
	}

	fseek(pf, 0, SEEK_END);
	long fileSize = ftell(pf);
	fseek(pf, 0, SEEK_SET);
	books_num = fileSize / sizeof(Book);

	fread(books, sizeof(Book), books_num, pf);
	fclose(pf);

	printf("%d\n", books_num);
}
//加载书籍信息
void Processlogin()
{
	//获取账户信息
	char name[LEN] = { 0 };
	char pwd[LEN] = { 0 };
	printf("账号:");
	scanf("%s", name);
	getchar();//清除缓存中的回车
	printf("密码:");
	scanf("%s", pwd);
	getchar();//清除缓存中的回车
	//在accounts账号数组搜索，如果没搜索到，提示"未找到该用户"，回到主界面
	//如果找到了，提示"登陆成功"
	for (int i = 0; i < accounts_num; i++)
	{
		if (strcmp(accounts[i].id, name) == 0 &&
			strcmp(accounts[i].pwd, pwd) == 0)
		{
			printf("登陆成功\n");
			switch (accounts[i].role)//判断role角色
									//学生或者管理员
			{
			case STUDENT:
				LoadBorrow();	//导入借阅列表
				for (;;)
				{
					ShowStudengtMenu();//展示学生界面
					printf("选择：");
					int choice = 0;
					scanf("%d", &choice);
					getchar();
					switch (choice)
					{
					case 1:
						ShowBook();
						break;
					case 2:
						SrarchBook(name);
						break;
					case 3:
						BorrowList(name);
						break;
					case 4:
						return;
					default:
						printf("非法输入!\n");
						break;
					}
				}
				break;
			case MANAGER:
				LoadOprLog();	//导入管理员日志
				LoadBorrow();	//导入借阅列表
				for (;;)
				{

					ShowMangerMenu();//展示管理员界面
					printf("选择:");
					int choice = 0;
					scanf("%d", &choice);
					getchar();//清除缓存中的回车
					switch (choice)
					{
					case 1:
						InBook(name);
						break;
					case 2:
						OutBook(name);
						break;
					case 3:
						BorrowBook(name);
						break;
					case 4:

						BackBook(name);
						break;
					case 5:
						ShowBook();
						break;
					case 6:
						SrarchBook(name);
						break;
					case 7:
						ShowOprLog();//打印日志
						break;
					case 8:
						return;
					default:
						printf("非法输入!\n");
						break;
					};
				}
				break;
			default:
				break;
			}
			return;
		}


	}
	printf("账号或密码输入错误\n");

	//判断role角色
	//学生或者管理员
}
//登录
void ShowFirstMenu()
{
	printf("========================\n");
	printf("1.登录\n");
	printf("2.注册\n");
	printf("3.退出\n");
	printf("========================\n");
}
//登录界面
void SavaSystemData()
{
	FILE* pf = fopen("account.db", "w");
	if (pf != NULL)
	{
		fwrite(accounts, sizeof(Account), accounts_num, pf);
		fclose(pf);
	}
	pf = fopen("book.db", "w");
	if (pf != NULL)
	{
		fwrite(books, sizeof(Book), books_num, pf);
		fclose(pf);
	}
	pf = fopen("borrow.db", "w");
	if (pf != NULL)
	{
		fwrite(borrows, sizeof(Borrow), borrows_num, pf);
		fclose(pf);
	}
	pf = fopen("log.db", "w");
	if (pf != NULL)
	{
		fwrite(logs, sizeof(OprLog), logs_num, pf);
		fclose(pf);
	}
}
//保存数据
void ProcessReg()
{
	printf("开始注册新用户...\n");

	Account account;
	printf("输入用户名:");
	scanf("%s", account.id);
	getchar();//清除缓存中的回车

	printf("输入密码:");
	scanf("%s", account.pwd);
	getchar();//清除缓存中的回车

	printf("输入角色(0:学生 1:管理员):");
	scanf("%d", &account.role);
	getchar();//清除缓存中的回车

	// 判断当前注册的用户名是否已被占用
	//如果用户名未重复，提示注册成功，返回主界面
	//如果用户名重复，提示用户名重复，回到主界面。
	//遍寻两个字符串，比较其元素是否相同
	for (int i = 0; i < accounts_num; i++)
	{
		if (strcmp(accounts[i].id, account.id) == 0
			&& accounts[i].role == account.role)//strcmp(,)判断两个字符串是否相同
		{
			printf("用户名重复\n");
			return;//return结束函数 break结束循环

		}


	}
	//账号唯一，先把数据放入数组中。
	accounts[accounts_num] = account;//结构体用等号表示把等号右边的内容粘贴到等号左边去
	accounts_num++;
	printf("注册成功\n");

}
//注册用户
void ShowMangerMenu()
{
	printf("=====================\n");
	printf("1.入库\n");
	printf("2.出库\n");
	printf("3.借书\n");
	printf("4.还书\n");
	printf("5.书籍列表\n");
	printf("6.搜索书籍\n");
	printf("7.操作日志\n");
	printf("8.返回\n");
	printf("=====================\n");
}

//管理员界面
void ShowStudengtMenu()
{
	printf("==================\n");
	printf("1.书籍列表\n");
	printf("2.搜索书籍\n");
	printf("3.借阅列表\n");
	printf("4.返回\n");
	printf("==================\n");

}
void InBook(char* mid)
{
	// 输入书名 和 册数 
	time_t now = time(0);
	char name[LEN] = { 0 };
	int count = 0;
	printf("输入书名:");
	scanf("%s", name);
	getchar();//清除缓存中的回车
	printf("输入册数:");
	scanf("%d", &count);
	getchar();//清除缓存中的回车

	// 加入书籍数组中，如果书名存在，只增加册数；否则新添加数据
	int i = 0;
	for (; i < books_num; i++)
	{
		if (strcmp(name, books[i].name) == 0)
		{
			books[i].count += count;
			break;
		}
	}

	if (i == books_num) // 新书
	{
		strcpy(books[books_num].name, name);
		books[books_num].count = count;
		books_num++;
	}

	// 记录日志
	OprLog log;
	log.timestamp = now;
	strcpy(log.mid, mid);
	log.oprType = IN;
	strcpy(log.data.d1.name, name);
	log.data.d1.count = count;

	logs[logs_num] = log;
	logs_num++;
	printf("入库成功\n");
	printf("log...%d\n", logs_num);
}
//入库

	//记录数据
void OutBook(char* mid)
{
	//输入书名信息
	char name[LEN] = { 0 };
	printf("书名：");
	scanf("%s", name);
	getchar();//清除缓存中的回车
	int count = 0;
	//查找书名信息，并删除
	int i = 0;
	for (; i <= books_num; i++)
	{

		if (strcmp(books[i].name, name) == 0)
		{
			count = books[i].count;
			for (int j = i + 1; j < books_num; j++)//当该书籍信息在数组中间
				strcpy(books[j - 1].name, books[j].name);

			books_num--;
			printf("出库成功\n");
			break;
		}
		if (i == books_num && i != 0)
		{
			printf("未找到该书籍信息\n");
			return;
		}
	}



	//写日志
	OprLog log;
	log.timestamp = time(0);
	strcpy(log.mid, mid);
	log.oprType = OUT;
	strcpy(log.data.d1.name, name);
	log.data.d1.count = count;


	logs[logs_num] = log;
	logs_num++;

	printf("log...%d\n", logs_num);
}
//出库
void BorrowBook(char* mid)
{
	/*输入学生ID，判断id合法性
	* 输入书籍名称，判断其合法性
	* 输入借书册数，
	* 如果合法，给相应的书籍册数减一，但是不能为负
	* 当书籍个数为0时，借书失败
	* 把借书的数据，输入到学生的borrow数组中
	* 记录log日志
	*/
	char id[LEN] = { 0 };
	char name[LEN] = { 0 };
	int count = 0;
	printf("id：");
	scanf("%s", id);
	getchar();//清除缓存中的回车
	int i = 0;
	for (; i < accounts_num; i++)
	{
		if (strcmp(accounts[i].id, id) == 0)
		{
			break;
		}
	}
	if (i == accounts_num)
	{
		printf("该id未注册\n");
		return;
	}
	printf("书名：");
	scanf("%s", name);
	getchar();
	printf("册数：");
	scanf("%d", &count);
	getchar();//清除缓存中的回车
	int j = 0;
	for (; j < books_num; j++)
	{
		if (strcmp(books[j].name, name) == 0)
		{

			if (count <= books[j].count)
			{
				books[j].count -= count;
				printf("借书成功\n");
				break;
			}
			else
			{
				printf("借书失败\n");
				printf("该书籍剩余库存:%d\n", books[j].count);
				return;
			}
		}
	}
	if (j == books_num)
	{
		printf("未找到该书籍\n");
		return;
	}
	//导入借阅信息
	Borrow borrow;
	borrow.timestamp = time(0);
	strcpy(borrow.id, id);
	strcpy(borrow.name, name);
	borrow.count = count;

	borrows[borrows_num] = borrow;
	borrows_num++;

	//记录日志
	OprLog log;
	log.timestamp = time(0);
	strcpy(log.mid, mid);
	log.oprType = BORROW;
	strcpy(log.data.d2.name, name);
	log.data.d2.count = count;
	strcpy(log.data.d2.sid, id);

	logs[logs_num] = log;
	logs_num++;
	printf("log....%d", logs_num);
}
//借书
void BackBook(char* mid)//还书
{
	/*输入学生ID，在借阅列表查找该学生，判断是否借书
	* 输入书籍名称，判断其合法性
	* 输入还书册数，
	* 如果合法，给相应的书籍册数相加，

	* 删除学生的借书数据
	* 记录log日志
	*/
	char id[LEN] = { 0 };
	char name[LEN] = { 0 };
	int count = 0;
	printf("id：");
	scanf("%s", id);
	getchar();//清除缓存中的回车
	int i = 0;
	for (; i < accounts_num; i++)
	{
		if (strcmp(accounts[i].id, id) == 0)
		{
			break;
		}
	}
	if (i == accounts_num)
	{
		printf("该id未注册\n");
		return;
	}
	printf("书名：");
	scanf("%s", name);
	getchar();
	printf("册数：");
	scanf("%d", &count);
	getchar();//清除缓存中的回车
	int j = 0;
	for (; j < books_num; j++)
	{
		if (strcmp(books[j].name, name) == 0)
		{

			books[j].count += count;
			printf("还书成功\n");
			break;

		}
	}
	if (j == books_num)
	{
		printf("未找到该书籍\n");
		return;
	}

	//删除借阅列表
	//筛选出借阅列表中书名为name的书，删除该项借阅记录
	for (int i = 0; i < borrows_num; i++)
	{
		if (strcmp(borrows[i].name, name) == 0)
		{
			for (int j = i + 1; j < borrows_num; j++)
			{
				borrows[j - 1] = borrows[j];
				borrows_num--;
			}
		}
	}
	//记录日志
	OprLog log;
	log.timestamp = time(0);
	strcpy(log.mid, mid);
	log.oprType = BACK;
	strcpy(log.data.d2.name, name);
	log.data.d2.count = count;
	strcpy(log.data.d2.sid, id);

	logs[logs_num] = log;
	logs_num++;
	printf("log....%d", logs_num);

}
//还书

void SrarchBook(char* mid)
{
	char key[LEN] = { 0 };
	printf("关键字：");
	scanf("%s", key);
	getchar();//清除缓存中的回车
	int i = 0;
	for (; i < books_num; i++)
	{
		if (strcmp(books[i].name, key) == 0)
		{
			printf("%s\t", books[i].name);
			printf("%d\n", books[i].count);

		}

	}
	for (int i =0; i < books_num; i++)
	{
		if (strcmp(books[i].name, key) != 0 &&
			strstr(books[i].name, key) != NULL)
		{
			printf("%s\t", books[i].name);
			printf("%d\n", books[i].count);

		}

	}
	/*if (i == books_num)
	{
		printf("书籍不存在");
		return;
	}*/
	/*定义书籍名称
	* 输入书籍名
	* 通过关键字搜索书籍（strstr函数）如果有输出书籍名和册数
	* 如果没有，输出未找到，返回主界面
	* 记录日志
	*/
	OprLog log;
	log.timestamp = time(0);
	strcpy(log.mid, mid);
	log.oprType = SEARCH;
	strcpy(log.data.key, key);

	logs[logs_num] = log;
	logs_num++;
	printf("log....%d\n", logs_num);

}
//搜索书籍
void ShowBook()
{
	if (books_num == 0)
		printf("库中书籍为空\n");
	for (int i = 0; i < books_num; i++)
	{
		printf("%s\t", books[i].name);
		printf("%d\n", books[i].count);
	}
}
//打印书籍列表
void LoadOprLog()
{
	printf("loading logs...");

	FILE* pf = fopen("log.db", "r");
	if (pf == NULL)
	{
		printf("0\n");
		return;
	}

	fseek(pf, 0, SEEK_END);
	long fileSize = ftell(pf);
	fseek(pf, 0, SEEK_SET);
	logs_num = fileSize / sizeof(OprLog);

	fread(logs, sizeof(OprLog), logs_num, pf);
	fclose(pf);

	printf("%d\n", logs_num);
}
//读取日志
void LoadBorrow()
{
	printf("loading borrow...");

	FILE* pf = fopen("borrow.db", "r");
	if (pf == NULL)
	{
		printf("0\n");
		return;
	}

	fseek(pf, 0, SEEK_END);
	long fileSize = ftell(pf);
	fseek(pf, 0, SEEK_SET);
	borrows_num = fileSize / sizeof(Borrow);

	fread(borrows, sizeof(Borrow), borrows_num, pf);
	fclose(pf);

	printf("%d\n", borrows_num);
}
//读取借阅信息
void ShowOprLog()
{
	for (int i = 0; i < logs_num; i++)
	{
		printf("%d\t", i + 1); // 打印序号

		// tm结构包含了时间戳对应的年月日 时分秒
		tm* t = localtime(&logs[i].timestamp);
		printf("%d-%d-%d %d:%d:%d\t", t->tm_year + 1900,
			t->tm_mon + 1, t->tm_mday, t->tm_hour,
			t->tm_min, t->tm_sec);

		printf("%s\t", logs[i].mid);

		switch (logs[i].oprType)
		{
		case IN:
			printf("%s\t", "入库操作");
			printf("%s\t", logs[i].data.d1.name);
			printf("%d\n", logs[i].data.d1.count);
			break;
		case OUT:
			printf("%s\t", "出库操作");
			printf("%s\t", logs[i].data.d1.name);
			printf("%d\n", logs[i].data.d1.count);
			break;
		case BORROW:
			printf("%s\t", "借书操作");
			printf("%s\t", logs[i].data.d2.name);
			printf("%s\t", logs[i].data.d2.sid);
			printf("%d\n", logs[i].data.d2.count);

			break;
		case BACK:
			printf("%s\t", "还书操作");
			printf("%s\t", logs[i].data.d2.name);
			printf("%s\t", logs[i].data.d2.sid);
			printf("%d\n", logs[i].data.d2.count);
			break;
		case SHOW:
			break;
		case SEARCH:
			printf("%s\t", "搜索操作");
			printf("%s\n", logs[i].data.key);
			break;
		default:
			break;
		}
	}
}
//查看日志
void BorrowList(char* mid)
{
	int i = 0;
	for (; i < borrows_num; i++)
	{
		if (strcmp(borrows[i].id, mid) == 0)
		{
			tm* t = localtime(&borrows[i].timestamp);//打印借阅时间
			printf("%d-%d-%d %d:%d:%d\t", t->tm_year + 1900,
				t->tm_mon + 1, t->tm_mday, t->tm_hour,
				t->tm_min, t->tm_sec);
			printf("%s\t", borrows[i].name);
			printf("%d\n", borrows[i].count);
		}
	}


}
//个人借阅列表